//

package maping;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
import java.util.Arrays;

/**
 *
 * @author niquefa
 */
public class OurMatrix {

    private double[][] values;
    private int rows;
    private int cols;

    public int getCols() {
        return cols;
    }

    public void setCols(int cols) {
        this.cols = cols;
    }

    public double[][] getM() {
        return values;
    }

    public void setM(double[][] m) {
        this.values = m;
        this.rows = m.length;
        this.cols = m[0].length;
    }

    public int getRows() {
        return rows;
    }

    public void setRows(int rows) {
        this.rows = rows;
    }
    public OurMatrix(int rows, int cols) {
        this.rows = rows;
        this.cols = cols;
        this.values = new double[rows][cols];
    }

    public double get(int row, int col) {
        if (row < 0 || col < 0 || col >= this.cols || row >= this.rows) {
            System.out.println("Posición inválida");
            return 0;
        }
        return this.values[row][col];
    }
    public int getRoundedValue(int row, int col) {
        if (row < 0 || col < 0 || col >= this.cols || row >= this.rows) {
            System.out.println("Posición inválida");
            return 0;
        }
        return (int)Math.round(this.values[row][col]);
    }

    public int[][] getRoundedMatrix() {
        int ret[][] = new int[this.rows][this.cols];
        for (int i = 0; i < this.rows; ++i) {
            for (int j = 0; j < this.cols; ++j) {
                ret[i][j] = (int) Math.round(this.values[i][j]);
            }
        }
        return ret;
    }

    public OurMatrix(double m[][]) {
        this.values = m.clone();
        this.rows = m.length;
        this.cols = m[0].length;
    }

    public void consolePrint() {
        for (int i = 0; i < this.rows; ++i) {
            for (int j = 0; j < this.cols; ++j) {
                System.out.print(this.values[i][j] + " ");
            }
            System.out.println();
        }
    }

    private static OurMatrix product(OurMatrix A, OurMatrix B) {
        if (A.getCols() != B.getRows()) {
            System.out.println("Dimensiones incorrectas");
            return null;
        }

        double sum = 0;
        //define el numero de filas de la matrix A  = m ;
        //define el numero de filas de la matrix C (resultado)
        int m = A.getRows();
        //define el numero de columnas de la matrix A
        //y el Numero de Filas de la matrix B = n
        int n = A.getCols();
        //define el numero de columnas de la matrix B  = p ;
        //defina el numero de Columnas de la matrix C (resulstado)
        int p = B.getCols();

        OurMatrix C = new OurMatrix(m, p);

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print("\t a[" + i + "][" + j + "] = " + A.get(i, j));
            }
            System.out.println();
        }

        System.out.println();
        System.out.println();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < p; j++) {
                System.out.print("\t b[" + i + "][" + j + "] = " + B.get(i, j));
            }
            System.out.println();
        }
        System.out.println();
        System.out.println();

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < p; j++) {
                sum = 0;
                String cad = "";
                for (int k = 0; k < n; k++) {
                    sum = A.get(i, k) * B.get(k, j) + sum;
                    if (cad.equals("")) {
                        cad = "" + cad + "a[" + i + "][" + k + "]*b[" + k + "][" + j + "]";
                    } else {
                        cad = "" + cad + "+a[" + i + "][" + k + "]*b[" + k + "][" + j + "]";
                    }
                }
                C.set(i, j, sum);
                System.out.print("\t" + cad);
                // System.out.print("\t c["+i+"]["+j+"] = " + c[i][j]);
                System.out.print(" = " + C.get(i, j));
            }
            System.out.println();
        }
        return C;
    }

    public void set(int row, int col, double val) {
        if (row < 0 || col < 0 || col >= this.cols || row >= this.rows) {
            System.out.println("Posición inválida");
            return;
        }
        this.values[row][col] = val;
    }

    public static double[][] getInverse(double[][] matrix) {
        double det = 1 / getDeterminant(matrix);
        double[][] nmatrix = getAtachedMatrix(matrix);
        multiply(det, nmatrix);
        return nmatrix;
    }

    public static void multiply(double n, double[][] matrix) {
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix.length; j++) {
                matrix[i][j] *= n;
            }
        }
    }

    public static double[][] getAtachedMatrix(double[][] matrix) {
        return getTransposeMatrix(getCofactorsMatrix(matrix));
    }

    public static double[][] getCofactorsMatrix(double[][] matrix) {
        double[][] nm = new double[matrix.length][matrix.length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix.length; j++) {
                double[][] det = new double[matrix.length - 1][matrix.length - 1];
                double detValor;
                for (int k = 0; k < matrix.length; k++) {
                    if (k != i) {
                        for (int l = 0; l < matrix.length; l++) {
                            if (l != j) {
                                int indice1 = k < i ? k : k - 1;
                                int indice2 = l < j ? l : l - 1;
                                det[indice1][indice2] = matrix[k][l];
                            }
                        }
                    }
                }
                detValor = getDeterminant(det);
                nm[i][j] = detValor * (double) Math.pow(-1, i + j + 2);
            }

        }
        return nm;
    }

    public static double[][] getTransposeMatrix(double[][] matrix) {
        double[][] nuevam = new double[matrix[0].length][matrix.length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix.length; j++) {
                nuevam[i][j] = matrix[j][i];
            }
        }
        return nuevam;

    }

    public static double getDeterminant(double[][] matrix) {
        double det;
        if (matrix.length == 2) {
            det = (matrix[0][0] * matrix[1][1]) - (matrix[0][1] * matrix[1][0]);
            return det;
        }
        double suma = 0;
        for (int i = 0; i < matrix.length; i++) {
            double[][] nm = new double[matrix.length - 1][matrix.length - 1];
            for (int j = 0; j < matrix.length; j++) {
                if (j != i) {
                    for (int k = 1; k < matrix.length; k++) {
                        int indice = -1;
                        if (j < i) {
                            indice = j;
                        } else if (j > i) {
                            indice = j - 1;
                        }
                        nm[indice][k - 1] = matrix[j][k];

                    }
                }

            }
            if (i % 2 == 0) {
                suma += matrix[i][0] * getDeterminant(nm);
            } else {
                suma -= matrix[i][0] * getDeterminant(nm);
            }
        }
        return suma;
    }

    public static void printMatrix(double[][] mat) {
        for (int i = 0; i < mat.length; i++) {
            System.out.println(Arrays.toString(mat[i]));
        }
    }

    public static void main(String[] args) {
        double[][] deltaS = {{1, 1, 1, 1, 1}, {0, 0, 1, 0, 1}, {0, -1, 0, 1, 0}, {1, -2, 0, 0, 0}, {0, 1, 1, 0, 0}};
        double[][] deltaA = {{30, 1, 1, 1, 1}, {14, 0, 1, 0, 1}, {1, -1, 0, 1, 0}, {-1, -2, 0, 0, 0}, {10, 1, 1, 0, 0}};
        double[][] deltaB = {{1, 30, 1, 1, 1}, {0, 14, 1, 0, 1}, {0, 1, 0, 1, 0}, {1, -1, 0, 0, 0}, {0, 10, 1, 0, 0}};
        double[][] deltaC = {{1, 1, 30, 1, 1}, {0, 0, 14, 0, 1}, {0, -1, 1, 1, 0}, {1, -2, -1, 0, 0}, {0, 1, 10, 0, 0}};
        double[][] deltaD = {{1, 1, 1, 30, 1}, {0, 0, 1, 14, 1}, {0, -1, 0, 1, 0}, {1, -2, 0, -1, 0}, {0, 1, 1, 10, 0}};
        double[][] deltaE = {{1, 1, 1, 1, 30}, {0, 0, 1, 0, 14}, {0, -1, 0, 1, 1}, {1, -2, 0, 0, -1}, {0, 1, 1, 0, 10}};
        System.out.println(getDeterminant(deltaA) / getDeterminant(deltaS));
        System.out.println(getDeterminant(deltaB) / getDeterminant(deltaS));
        System.out.println(getDeterminant(deltaC) / getDeterminant(deltaS));
        System.out.println(getDeterminant(deltaD) / getDeterminant(deltaS));
        System.out.println(getDeterminant(deltaE) / getDeterminant(deltaS));
    }
    public OurMatrix product(OurMatrix B) {
        OurMatrix A = this;
        if (A.getCols() != B.getRows()) {
            System.out.println("Dimensiones incorrectas");
            return null;
        }

        double sum = 0;
        //define el numero de filas de la matrix A  = m ;
        //define el numero de filas de la matrix C (resultado)
        int m = A.getRows();
        //define el numero de columnas de la matrix A
        //y el Numero de Filas de la matrix B = n
        int n = A.getCols();
        //define el numero de columnas de la matrix B  = p ;
        //defina el numero de Columnas de la matrix C (resulstado)
        int p = B.getCols();

        OurMatrix C = new OurMatrix(m, p);
        /*
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print("\t a[" + i + "][" + j + "] = " + A.get(i, j));
            }
            System.out.println();
        }

        System.out.println();
        System.out.println();
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < p; j++) {
                System.out.print("\t b[" + i + "][" + j + "] = " + B.get(i, j));
            }
            System.out.println();
        }
        System.out.println();
        System.out.println();*/

        for (int i = 0; i < m; i++) {
            for (int j = 0; j < p; j++) {
                sum = 0;
                String cad = "";
                for (int k = 0; k < n; k++) {
                    sum = A.get(i, k) * B.get(k, j) + sum;
                    if (cad.equals("")) {
//                        cad = "" + cad + "a[" + i + "][" + k + "]*b[" + k + "][" + j + "]";
                    } else {
//                        cad = "" + cad + "+a[" + i + "][" + k + "]*b[" + k + "][" + j + "]";
                    }
                }
                C.set(i, j, sum);
//                System.out.print("\t" + cad);
                // System.out.print("\t c["+i+"]["+j+"] = " + c[i][j]);
//                System.out.print(" = " + C.get(i, j));
            }
//            System.out.println();
        }
        return C;
    }

}

//